﻿#include <learn/ais/ais_curve.h>
#include <learn/alg/alg_projection.h>

using namespace xi;
using namespace xi::ais;
using namespace xi::alg;

AIS_Curve::AIS_Curve(std::shared_ptr<Geom_Curve<3>> curve) : m_curve(curve), m_sampler(new Alg_Uniform_Sampler)
{
    this->m_collisionFunc = [&](AIS_MouseMsg *msg) -> bool {
        // 获得屏幕点和鼠标位置
        Vec2f p = msg->move;
        Vec3 emit = convert<double>(msg->emit(p)).normalize();
        Vec3 P = convert<double>(msg->toSpace(p));

        auto t = Alg_Projection<3>::parallel(m_curve, P, emit, (m_curve->first_param() + m_curve->last_param()) / 2, 1e-2);

        // 如果小于指定深度，则记录下来
        auto Q = m_curve->value(t);
        auto S = msg->toScreen(convert<float>(Q));
        if (S.z() < msg->depth && cross((P - Q).normalize(), emit).modulus() < 1e-2)
        {
            msg->depth = Q.z();
            msg->obj = this;
            return true;
        }
        return false;
    };
}

std::shared_ptr<Geom_Curve<3>> AIS_Curve::curve() const
{
    return m_curve;
}

std::vector<Vec3f> AIS_Curve::sample(std::size_t num) const
{
    // 修改采样器的采样数量
    auto sampler = std::static_pointer_cast<Alg_Uniform_Sampler>(m_sampler);
    sampler->uCount = num;

    auto samples = sampler->perform(m_curve->first_param(), m_curve->last_param());
    std::vector<Vec3f> points(samples.size());
    for (std::size_t i = 0; i < samples.size(); ++i)
        points[i] = convert<float>(m_curve->value(samples[i]));
    return points;
}

void AIS_Curve::visit(AIS_InitMsg *msg)
{
    // 利用工厂创建渲染器
    if (msg->factory)
        m_renderer.reset(msg->factory->create_product("AIS_Curve"));
}
